#![allow(non_snake_case, dead_code)]

use super::camera::Camera;
use super::camera::CameraMovement::{Backward, Forward, Left, Right};
use glfw::{Action, Key, WindowEvent};
use std::os::raw::c_void;
use std::path::Path;
use std::sync::mpsc::Receiver;

use image::DynamicImage::*;
use image::GenericImage;

pub fn process_input(window: &mut glfw::Window, delta_time: f32, camera: &mut Camera) {
    if window.get_key(Key::Escape) == Action::Press {
        window.set_should_close(true);
    }

    if window.get_key(Key::W) == Action::Press || window.get_key(Key::Up) == Action::Press {
        camera.process_keyboard(Forward, delta_time);
    }
    if window.get_key(Key::S) == Action::Press || window.get_key(Key::Down) == Action::Press {
        camera.process_keyboard(Backward, delta_time);
    }
    if window.get_key(Key::A) == Action::Press || window.get_key(Key::Left) == Action::Press {
        camera.process_keyboard(Left, delta_time);
    }
    if window.get_key(Key::D) == Action::Press || window.get_key(Key::Right) == Action::Press {
        camera.process_keyboard(Right, delta_time);
    }
}

pub fn process_events(
    events: &Receiver<(f64, glfw::WindowEvent)>,
    first_mouse: &mut bool,
    last_x: &mut f32,
    last_y: &mut f32,
    camera: &mut Camera,
) {
    for (_, event) in glfw::flush_messages(events) {
        match event {
            WindowEvent::FramebufferSize(width, height) => unsafe { gl::Viewport(0, 0, width, height) },
            WindowEvent::CursorPos(x_pos, y_pos) => {
                let (x_pos, y_pos) = (x_pos as f32, y_pos as f32);
                if *first_mouse {
                    *last_x = x_pos;
                    *last_y = y_pos;
                    *first_mouse = false;
                }
                let x_offset = x_pos - *last_x;
                let y_offset = *last_y - y_pos;
                *last_x = x_pos;
                *last_y = y_pos;
                camera.process_mouse_movement(x_offset, y_offset, true);
            }
            WindowEvent::Scroll(_, y_offset) => {
                camera.process_mouse_scroll(y_offset as f32);
            }
            _ => {}
        }
    }
}

pub unsafe fn load_texture(path: &str) -> u32 {
    let mut texture_id = 0;
    gl::GenTextures(1, &mut texture_id);
    let img = image::open(&Path::new(path)).expect("Failed to load texture");
    let format = match img {
        ImageLuma8(_) => gl::RED,
        ImageLumaA8(_) => gl::RG,
        ImageRgb8(_) => gl::RGB,
        ImageRgba8(_) => gl::RGBA,
    };
//    let img = img.flipv();
    let data = img.raw_pixels();
    gl::BindTexture(gl::TEXTURE_2D, texture_id);
    gl::TexImage2D(
        gl::TEXTURE_2D,
        0,
        format as i32,
        img.width() as i32,
        img.height() as i32,
        0,
        format,
        gl::UNSIGNED_BYTE,
        &data[0] as *const u8 as *const c_void,
    );
    gl::GenerateMipmap(gl::TEXTURE_2D);

    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);

    texture_id
}
